# = Class ASTBool
# Inherits from ASTExpression. Represents the implementation of an AST especifically designed
# for boolean instructions instructions

class ASTBool < ASTExpression
  # == Attributes inherited from ASTExpression
  # node, children
  
  # == Methods inherited from ASTExpression
  # check(), run(), to_s_children(im)

  # Method to evaluate the boolean expresion
  # === Parameters
  # * parent_sym_table: Symbol table passed by the parent AST
  # * func_table: Function symbol table passed by the parent AST
  # === Return value
  # nil if executed with success or an error message
  def eval parent_sym_table, func_table

    if nil == @children
      if (@node.kind_of?TkTrue)
        @value = true
      else
        @value = false
      end
      return nil
    end

    msg = @children[0].eval parent_sym_table, func_table
    if nil != msg
      return msg
    end
    if nil == @children[1]
      @value = !@children[0].value
      return nil
    end
    msg = @children[1].eval parent_sym_table, func_table
    if nil != msg
      return msg
    end

    case @node.value
    when '<'
      @value = children[0].value < children[1].value
    when '>'
      @value = children[0].value > children[1].value
    when '<='
      @value = children[0].value <= children[1].value
    when '>='
      @value = children[0].value >= children[1].value
    when '='
      @value = children[0].value == children[1].value
    when '!='
      @value = children[0].value != children[1].value
    when '&&'
      @value = children[0].value && children[1].value
    when '||'
      @value = children[0].value || children[1].value
    end

    nil
  end

  # Method to check the static correctitude of the boolean expresion
  # === Parameters
  # * parent_sym_table: Symbol table passed by the parent AST
  # * func_table: Function symbol table passed by the pare
  # * func_type: Type of valid return value
  # === Return value
  # nil if executed with success or an error message
  def check parent_sym_table, func_table, func_type

    if nil == @children
      if (@node.kind_of?TkTrue) || (@node.kind_of?TkFalse)
        @type = 'Booleano'
        return nil
      end
      # The node is an operator and there are no operands
      return "Error interno: ASTBool sin operadores (#{error_location})"
    end
    if nil == @children[0]
      return "Error interno: ASTBool sin operador izquierdo (#{error_location})"
    end
    if nil == @children[1]
      msg = @children[0].check parent_sym_table, func_table, func_type
      if nil != msg
        return msg
      end
      if (@node.kind_of?TkNot)
        if @children[0].type != 'Booleano'
            return "Tratando de negar '#{@children[0].type}' (#{@children[0].error_location})"
        end
        @type = 'Booleano'
        return nil
      end
      return "Error interno: ASTBool sin operador derecho (#{error_location})"
    end

    msg = @children[0].check parent_sym_table, func_table, func_type
    if nil != msg
      return msg
    end
    msg = @children[1].check parent_sym_table, func_table, func_type
    if nil != msg
      return msg
    end

    case @node.value
    when '<', '>', '<=', '>='
      if @children[0].type != 'num'
          return "Tratando comparar relación '#{@children[0].type}' (#{@children[0].error_location})"
      end
      if @children[1].type != 'num'
          return "Tratando comparar relación '#{@children[1].type}' (#{@children[1].error_location})"
      end
    when '='
      if @children[0].type != 'num' && @children[0].type != 'Booleano'
          return "Tratando comparar '#{@children[0].type}' (#{@children[0].error_location})"
      end
      if @children[1].type != 'num' && @children[1].type != 'Booleano'
          return "Tratando comparar '#{@children[1].type}' (#{@children[1].error_location})"
      end
      if @children[0].type != @children[1].type
          return "Tratando de comparar tipos incompatibles '#{@children[0].type}'" +
                ", '#{@children[1].type}' (#{@children[0].error_location})"
      end
    when '!='
      if @children[0].type != 'num'
          return "Tratando usar (!=) sobre '#{@children[0].type}' (#{@children[0].error_location})"
      end
      if @children[1].type != 'num'
          return "Tratando ejecutar disyunción sobre '#{@children[1].type}' (#{@children[1].error_location})"
      end
    when '&&'
      if @children[0].type != 'Booleano'
          return "Tratando ejecutar disyunción sobre '#{@children[0].type}' (#{@children[0].error_location})"
      end
      if @children[1].type != 'Booleano'
          return "Tratando ejecutar disyunción sobre '#{@children[1].type}' (#{@children[1].terror_locationo_s})"
      end
    when '||'
      if @children[0].type != 'Booleano'
          return "Tratando ejecutar conjunción sobre '#{@children[0].type}' (#{@children[0].error_location})"
      end
      if @children[1].type != 'Booleano'
          return "Tratando ejecutar conjunción sobre '#{@children[1].type}' (#{@children[1].error_location})"
      end
    end
    @type = 'Booleano'

    nil
  end
end